Terraformのimportコマンドとimportブロックを試してみた
※Terraform v1.7.0を使用しています。
importコマンド
terraform importコマンドは、指定した既存リソース及びその設定情報の定義をtfstateファイルに生成するコマンドです。
- 公式ドキュメント
① インポート対象リソースの作成
「manabe-test-instance」というNameタグを付けたEC2インスタンスを作成します。
② resourceブロックの作成
tfファイルに、インポート対象リソース用のresourceブロックを定義します。
この時点では、パラメータの定義は不要です。
例えば、「aws_instance」においては「ami」と「instance_type」が必須パラメータですが未定義で問題ありません。
resource "aws_instance" "sample1" { }
③ importコマンドの実行
importコマンドの使用方法は以下の通りです。
terraform import [resourceブロックのtype].[resourceブロックのname] [リソースID]
実行します。
$ terraform import aws_instance.sample1 i-0da09fb0d4fe82991 ~~ 省略 ~~ Import successful! The resources that were imported are shown above. These resources are now in your Terraform state and will henceforth be managed by Terraform.
importコマンドが成功した後、tfstateファイルを見るとリソースの定義が生成されていることが確認できます。
④ tfファイルの修正
tfファイルのresourceブロックの中身は未定義のままなので、terraform planコマンドで差分を確認しつつ修正していきます。
resource "aws_instance" "sample1" { // 追記 ami = "ami-0de5b371cbca0edcb" instance_type = "t2.micro" tags = { Name = "manabe-test-instance" } }
差分がなくなりました。
$ terraform plan ~~ 省略 ~~ No changes. Your infrastructure matches the configuration.
importブロック
importブロックはTerraform v1.5.0 でリリースされた機能です。
importコマンドではリソースの定義はtfstateファイル上にしか生成されず、tfファイルは手書きで編集する必要がありましたが、importブロックを使用するとtfファイル上にもリソース定義を自動生成することが可能です。
また、importコマンドは1リソースずつ行う必要がありますが、importブロックは複数リソースをまとめて実行することができます。
importブロックの一般的な使用方法として、resourceブロックをimportブロックによって自動生成するパターンと、resourceブロックを事前に作成しておくパターンがあります。
resourceブロックをimportブロックによって自動生成するパターン
① インポート対象リソースの作成
先ほど同様、「manabe-test-instance」というNameタグを付けたEC2インスタンスを作成します。
※先の手順で作成したインスタンスは、terraform destroyコマンドを使用して削除済です。
② importブロックの作成
以下のように定義します。
import { id = "i-052562f6eee9d60d9" to = aws_instance.sample1 }
「id」及び「to」は必須パラメータです。
- 「id」:[リソースID]
- 「to」:[resourceブロックのtype].[resourceブロックのname]
③ tfファイルにリソース定義をインポート
以下のように、「-generate-config-out=[任意の名前].tf」というオプションを付けてterraform planコマンドを実行します。
※生成するファイルが存在する場合エラーとなるので、存在しないファイル名を指定しなければなりません。
$ terraform plan -generate-config-out=import.tf aws_instance.sample1: Preparing import... [id=i-052562f6eee9d60d9] aws_instance.sample1: Refreshing state... [id=i-052562f6eee9d60d9] Planning failed. Terraform encountered an error while generating this plan. ╷ │ Warning: Config generation is experimental │ │ Generating configuration during import is currently experimental, and the generated configuration format may change in future versions. ╵ ╷ │ Error: Conflicting configuration arguments │ │ with aws_instance.sample1, │ on import.tf line 14: │ (source code not available) │ │ "ipv6_address_count": conflicts with ipv6_addresses ╵ ╷ │ Error: Conflicting configuration arguments │ │ with aws_instance.sample1, │ on import.tf line 15: │ (source code not available) │ │ "ipv6_addresses": conflicts with ipv6_address_count
実行後、本オプションで指定したtfファイルが作成され、中にリソース定義が生成されます。
また、import.tfファイルが生成されるのと同時に、terraform planコマンドの実行結果としていくつかエラーが出力されています。
Terraformによって生成されたファイルには共存しないパラメータが存在する可能性があり、存在する場合このようにエラーが出力されます。
本手順の場合、自動生成されたresourceブロック内のパラメータ「ipv6_addresses」と「ipv6_address_count」が競合していました。
「ipv6_address_count」をコメントアウトし、オプションを付けずにterraform planコマンドを実行します。
$ terraform plan ~~ 省略 ~~ Plan: 1 to import, 0 to add, 0 to change, 0 to destroy.
エラーがなくなりました。
④ tfstateファイルにリソース定義をインポート
terraform applyコマンドを実行します。
$ terraform apply aws_instance.sample1: Preparing import... [id=i-052562f6eee9d60d9] aws_instance.sample1: Refreshing state... [id=i-052562f6eee9d60d9] ~~ 省略 ~~ Apply complete! Resources: 1 imported, 0 added, 0 changed, 0 destroyed.
実行後、tfstateファイルにリソース定義が自動生成されていることが確認できます。
ここまでの手順が完了したら、importブロックは削除して大丈夫です。
resourceブロックを事前に作成しておくパターン
importブロックの「to」に定義したresourceのアドレスがtfファイル上に既に存在する場合、terraformはtfファイルの自動生成を行わず、既存のresourceブロックと実際のリソースが紐づけられます。
事前にresourceブロックの定義が可能であればこちらのパターンが使用可能です。
① インポート対象リソースの作成
先ほど同様、「manabe-test-instance」というNameタグを付けたEC2インスタンスを作成します。
※先の手順で作成したインスタンスは、terraform destroyコマンドを使用して削除済です。
② importブロック、resourceブロックの作成
以下のようにimportブロック、resourceブロックを定義します。
import { id = "i-073eddd24e734b1ff" to = aws_instance.sample1 } resource "aws_instance" "sample1" { ami = "ami-0de5b371cbca0edcb" instance_type = "t2.micro" tags = { Name = "manabe-test-instance" } }
③ インポートの実行
terraform applyコマンドを実行します。
$ terraform apply aws_instance.sample1: Preparing import... [id=i-073eddd24e734b1ff] aws_instance.sample1: Refreshing state... [id=i-073eddd24e734b1ff] ~~ 省略 ~~ Apply complete! Resources: 1 imported, 0 added, 1 changed, 0 destroyed.
実行後、tfstateファイルにリソース定義が生成されていることが確認できます。
ここまでの手順が完了したら、importブロックは削除して大丈夫です。
以上で本手順は終了です。
最後に
importブロックはtfファイルの生成も可能なので非常に便利ですが、本番環境等においてterraform applyコマンドを使用するのは少し怖い気もします。
使用する場合は既存リソースの再生成等が行われないように注意しないといけません。
また、今回はTerraformの標準機能を使用したインポート方法をご紹介しましたが、「Terraformer」や「terracognita」といったツールを使用したインポート方法も存在するようなので、今度そちらも試してみようと思います。